package com.alpesressources.comexpert;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.alpesressources.comexpert.bo.request.Request;
import com.alpesressources.comexpert.bo.response.ErrorResponse;
import com.alpesressources.comexpert.bo.response.Response;
import com.alpesressources.comexpert.bo.response.ErrorResponse.EnumErrorCode;
import com.alpesressources.comexpert.util.MyJsonDeserializer;
import com.alpesressources.comexpert.util.MyJsonSerializer;
import com.alpesressources.comexpert.util.QueryStringParser;
import com.alpesressources.comexpert.util.TokenBase;

public class EntryPoint extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static final String VERSION = "0.11.0";
	private static Logger logger = Logger.getLogger(EntryPoint.class);

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HashMap<String, Object> m = QueryStringParser.parse(request
				.getQueryString());
		String remoteAddr = request.getRemoteAddr();

		MyJsonSerializer myJsonSerializer = new MyJsonSerializer();

		try {
			logger.debug("QueryString : " + m);
			if (!validateQuerySQtring(m, response)) {
				Response r = new Response();
				ErrorResponse errorResponse = new ErrorResponse();

				errorResponse.setErrorCode(EnumErrorCode.INVALID_QUERY_STRING);
				r.setErrorResponse(errorResponse);

				response.getOutputStream().write(
						myJsonSerializer.serialize(r).getBytes());
				return;
			}

			AAction action = createAction(m);
			if (action != null) {

				String json = IOUtils.toString(request.getInputStream(),
						"UTF-8");

				logger.debug("JSon : " + json);

				if (json != null && !json.isEmpty()) {
					MyJsonDeserializer myJsonDeserializer = new MyJsonDeserializer(
							action.getObjectClass());

					Request postRequest = myJsonDeserializer
							.deserializeRequest(json);
					if (!postRequest.isHashKeyValid()) {
						Response r = new Response();
						ErrorResponse errorResponse = new ErrorResponse();

						errorResponse
								.setErrorCode(EnumErrorCode.INVALID_HASHKEY);
						r.setErrorResponse(errorResponse);

						response.getOutputStream().write(
								myJsonSerializer.serialize(r).getBytes());
						return;
					}

					if (!((String) m.get("action")).equals("Authentification")) {
						if (!TokenBase.getInstance().isValid(
								postRequest.getToken(), remoteAddr)) {
							Response r = new Response();
							ErrorResponse errorResponse = new ErrorResponse();

							errorResponse
									.setErrorCode(EnumErrorCode.INVALID_TOKEN);
							r.setErrorResponse(errorResponse);

							response.getOutputStream().write(
									myJsonSerializer.serialize(r).getBytes());
							return;
						}
					}

					Calendar c = Calendar.getInstance();
					c.add(Calendar.MINUTE, -10);
					Date from = c.getTime();
					c.add(Calendar.MINUTE, 20);
					Date to = c.getTime();

					if (postRequest.getRequestDate().before(from)
							|| postRequest.getRequestDate().after(to)) {
						Response r = new Response();
						ErrorResponse errorResponse = new ErrorResponse();

						errorResponse
								.setErrorCode(EnumErrorCode.INVALID_REQUEST_DATE);
						r.setErrorResponse(errorResponse);

						response.getOutputStream().write(
								myJsonSerializer.serialize(r).getBytes());
						return;
					}

					action.processPost(this.getServletConfig(), m,
							postRequest.getData(), response);

					TokenBase.getInstance().create(action.getToken(),
							remoteAddr);

				} else {
					Response r = new Response();
					ErrorResponse errorResponse = new ErrorResponse();

					errorResponse.setErrorCode(EnumErrorCode.EMPTY_MESSAGE);
					r.setErrorResponse(errorResponse);

					response.getOutputStream().write(
							myJsonSerializer.serialize(r).getBytes());
				}
			}
		} catch (Exception e) {
			logger.error(e);

			Response r = new Response();
			ErrorResponse errorResponse = new ErrorResponse();

			errorResponse.setErrorCode(EnumErrorCode.INVALID_MESSAGE);
			r.setErrorResponse(errorResponse);

			response.getOutputStream().write(
					myJsonSerializer.serialize(r).getBytes());
		}
	}

	private AAction createAction(HashMap<String, Object> m) {
		AAction action = null;

		String className = EntryPoint.class.getPackage().getName() + "."
				+ (String) m.get("action");

		logger.debug("Try to instanciate " + className + " object");

		try {
			@SuppressWarnings("unchecked")
			Class<? extends AAction> c = (Class<? extends AAction>) Class
					.forName(className);
			action = (AAction) c.newInstance();

		} catch (ClassNotFoundException e) {
			logger.error(e);
		} catch (InstantiationException e) {
			logger.error(e);
		} catch (IllegalAccessException e) {
			logger.error(e);
		}

		return action;
	}

	private boolean validateQuerySQtring(HashMap<String, Object> m,
			HttpServletResponse response) {
		if (!m.containsKey("action") || !m.containsKey("dossier")) {
			return false;
		}

		return true;
	}
}
